package pactice_handler

import (
	"encoding/json"
	"fmt"
	"net/http"
	"peilian-api/app/controllers/web_report"
	"peilian-api/app/global/bind"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/app/services"
	"peilian-api/app/services/report_service"
	"peilian-api/utils/format"
	"sort"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

func init() {
	web_report.FetchSkillComment = FetchSkillComment
	web_report.CalculateStandardVariance = calculateStandardVariance
	web_report.FetchSkillCommentExt = fetchSkillCommentExt
	web_report.FetchPromoteComment = fetchPromoteComment
	web_report.SuggestComments = suggestComments
	web_report.AbilityComments = abilityComments
}

var civilScoreWeight = map[string]float64{
	"综合分析能力":   0.21,
	"言语表达能力":   0.22,
	"应急应变能力":   0.16,
	"计划组织协调能力": 0.16,
	"人际交往能力":   0.15,
	"自我情绪控制":   0.1,
}

var skillComments, _ = tables.DefaultTrick.GetSkillTrick()

var abilityComments, _ = tables.DefaultTrick.GetAbilityTrick()

// 建议评论通用岗位文案
var suggestCommonComments, _ = tables.DefaultTrick.GetCommonSuggestTrick()

// 建议评论文案
var suggestComments, _ = tables.DefaultTrick.GetSuggestTrick()

func FetchSkillComment(skill string, score float64) string {
	if comments := skillComments[skill]; len(comments) > 0 {
		if score > 90 {
			return comments["A"]
		} else if score >= 75 && score <= 90 {
			return comments["B"]
		} else if score >= 60 && score <= 74 {
			return comments["C"]
		} else {
			return comments["D"]
		}
	} else {
		return ""
	}
}
func fetchCivilComment(skill string, score float64) string {
	if comments := skillComments[skill]; len(comments) > 0 {
		if score >= 85 {
			return comments["A"]
		} else if score >= 60 {
			return comments["B"]
		} else if score >= 40 {
			return comments["C"]
		} else {
			return comments["D"]
		}
	} else {
		return ""
	}
}

func fetchCivilEmotionComment(skill string, score float64) string {
	if comments := skillComments[skill]; len(comments) > 0 {
		if score >= 60 {
			return comments["A"]
		} else if score >= 30 {
			return comments["B"]
		} else {
			return comments["C"]
		}
	} else {
		return ""
	}
}
func fetchSkillCommentExt(skill string, avg float64, variance float64, asrScore float64, emotionScore float64, flag bool) string {
	if flag {
		if avg >= 60 && variance <= 0.0625 {
			return skillComments[skill]["A"]
		} else if avg >= 60 && variance >= 0.0625 {
			return skillComments[skill]["B"]
		} else if avg < 60 && variance < 0.0625 {
			return skillComments[skill]["C"]
		} else if avg < 60 && variance > 0.0625 {
			return skillComments[skill]["D"]
		}
		return skillComments[skill]["D"]
	} else {
		if avg >= 60 && emotionScore >= 60 && asrScore >= 60 && variance <= 0.0625 {
			return skillComments[skill]["A"]
		} else if avg >= 60 && emotionScore >= 60 && asrScore < 60 && variance >= 0.0625 {
			return skillComments[skill]["B"]
		} else if avg >= 60 && emotionScore < 60 && asrScore >= 60 && variance >= 0.0625 {
			return skillComments[skill]["C"]
		} else if avg < 60 && variance <= 0.0625 {
			return skillComments[skill]["D"]
		} else if avg < 60 && variance >= 0.0625 {
			return skillComments[skill]["E"]
		}
		return skillComments[skill]["E"]
	}
}

// 专注度计算方差
func calculateVariance(v []float64) (float64, float64) {
	var absorbedSum float64 = 0.00
	length := len(v)
	for i := 0; i < length; i++ {
		absorbedSum += v[i]
	}
	avg := absorbedSum / float64(length)
	absorbedSum = 0.00
	for i := 0; i < length; i++ {
		absorbedSum += (v[i] - avg) * (v[i] / avg)
	}
	return absorbedSum / float64(length), avg
}

// 计算方差
func calculateStandardVariance(v []float64) (float64, float64) {
	var absorbedSum float64 = 0.00
	length := len(v)
	for i := 0; i < length; i++ {
		absorbedSum += v[i]
	}
	avg := absorbedSum / float64(length)
	absorbedSum = 0.00
	for i := 0; i < length; i++ {
		absorbedSum += ((v[i] - avg) / avg) * ((v[i] - avg) / avg)
	}
	return absorbedSum / float64(length), avg
}

// 求平均值
func calculateAvg(data []float64) float64 {
	var sum float64 = 0.00
	length := len(data)
	for i := 0; i < length; i++ {
		sum += data[i]
	}
	avg := sum / float64(length)
	return avg
}

// 语言表述得分文案
func fetchLanguageExpressText(score int) string {
	var express = "您在面试过程中缺乏自信心，应当增加行业知识储备、多加练习。"
	if score >= 95 {
		express = "您在面试过程中一直充满自信，能够很好地回答问题。给面试官留下了深刻的印象。"
	} else if score >= 90 && score < 95 {
		express = "您在面试过程中存在一些自信心不足，保持自信更容易获得面试官的认可。"
	} else if score < 90 {
		express = "您在面试过程中缺乏自信心，应当增加行业知识储备、多加练习。"
	}
	return express
}

// 自信度文案
func fetchConfidenceText(score float64) string {
	var express = skillComments["自信度"]["C"]
	if score > 90 {
		express = skillComments["自信度"]["A"]
	} else if score >= 75 && score <= 90 {
		express = skillComments["自信度"]["B"]
	} else if score >= 60 && score <= 75 {
		express = skillComments["自信度"]["C"]
	}
	return express
}

// 专注度文案
func fetchAbsorbedText(avg float64, variance float64) string {
	var express = skillComments["专注度"]["C"]
	if avg >= 60 && variance <= 0.0625 {
		express = skillComments["专注度"]["A"]
	} else if avg >= 60 && variance > 0.0625 {
		express = skillComments["专注度"]["B"]
	} else if avg < 60 {
		express = skillComments["专注度"]["C"]
	}
	return express
}

// 语言表述 & 威少主题 建议文案
// tp = 1 是 语言表述文案  2 围绕主题文案
func fetchSuggestComment(tp int, score int) string {
	s := strconv.Itoa(tp)
	if score >= 75 {
		return skillComments[s]["A"]
	} else if score > 50 && score <= 74 {
		return skillComments[s]["B"]
	} else if score >= 25 && score <= 50 {
		return skillComments[s]["C"]
	} else if score >= 0 && score <= 24 {
		return skillComments[s]["D"]
	}
	return skillComments[s]["A"]
}

// 获取有待提升文案
func fetchPromoteComment(s string, score int, criteria string) string {
	if score >= 75 {
		return suggestComments[s][criteria]["A"]
	} else if score > 50 && score <= 74 {
		return suggestComments[s][criteria]["B"]
	} else if score >= 25 && score <= 50 {
		return suggestComments[s][criteria]["C"]
	} else if score >= 0 && score <= 24 {
		return suggestComments[s][criteria]["D"]
	}
	return suggestComments[s][criteria]["A"]
}

// 判断缺少要点个数 以及 评分最小的要点 1,2,3,4
func lackMainPointSum(mainPoint string) (int, int) {
	if len(mainPoint) == 0 {
		return 0, 0
	}
	sum := 0 // 要点个数统计
	var ptd []tables.PointTextDetail
	// bMainPoint, _ := json.Marshal(mainPoint)
	json.Unmarshal([]byte(mainPoint), &ptd)
	pointType := ptd[0].Type
	score := ptd[0].Score
	for i := 0; i < len(ptd); i++ {
		if ptd[i].Score <= 50 {
			sum++
		}
		if score < ptd[i].Score {
			pointType = ptd[i].Type
		}
	}
	num := (tables.ConstMainPointNum)[pointType]
	return sum, num
}

func updateScore(ctx *gin.Context, sessionId int) error {
	questions, err := services.FindQuestionsBySessionId(sessionId)
	if err != nil {
		return err
	}
	for _, question := range questions {
		ans_text := question.AnswerText
		speakTime := question.SpeakTime
		var pointScore float64 = question.MainPointScore // 要点关键词评分
		var themeScore float64 = 0.00                    // 主题评分
		// var pts []tables.PointTextStruct        // 要点评分数据结构
		//var themeArr []string                   // 主题评分数据结构
		updates := make(map[string]interface{}) // 更新数据

		if len(ans_text) < 50 || speakTime < 10 {
			continue
			// updates["asr_score"] = 0.00
			// updates["main_point_score"] = 0.00
			// updates["theme_score"] = 0.00
			// updates["language_score"] = 0.00
			// updates["mood"] = 0.00
		} else {
			// 重试3次
			for i := 0; i < 3; i++ {
				if len(question.AnswerAudio) == 0 {
					rq, _ := new(tables.RealQues).GetRealQuestionById(int(question.ID))
					question = rq
					time.Sleep(300 * time.Millisecond)
					continue
				}
				break
			}
			// asr 评分
			asrScore := report_service.FetchLanguageComment(question.AnswerText) // asr_score
			// 语调气场
			toneScore := report_service.FetchEmotion(variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + question.AnswerAudio)
			// 自信度(语气词评分)
			moodScore := report_service.FetchMood(question.AnswerText)
			// 语言流畅度
			languageFluencyScore := asrScore*0.5 + moodScore*0.5
			// 语言表达能力 = (语言流畅度+语调) / 2
			languageScore := (toneScore + languageFluencyScore) / 2.0

			// 主题评分
			//themeText := question.Question.KeyWords
			//if len(themeText) != 0 {
			//	_ = json.Unmarshal([]byte(themeText), &themeArr)
			themeScore = report_service.FetchFocusTopicScore(question.QuestionText, ans_text)
			logicScore := report_service.FetchLogicScore(question.QuestionText, ans_text)
			if themeScore < logicScore {
				// 逻辑得分是与围绕主题得分相比取最小值
				logicScore = themeScore
			}
			//}

			// 题目评测得分
			topicScore := languageScore*0.2 + themeScore*0.3 + pointScore*0.5
			if question.Question.CareerID == tables.QCivilServant {
				topicScore = themeScore*0.35 + question.MainPointScore*0.65
			}

			// 人格
			cr, _ := report_service.FetchCharacter(ans_text)
			characterInfoByte, _ := json.Marshal(cr.Personality)

			// 表现力
			performanceScore := languageScore*0.5 + themeScore*0.5

			// 表达能力
			expressScore := (languageFluencyScore + toneScore + themeScore + question.MainPointScore) / 4.0

			//公务员言语表达能力: 语言流畅度*0.3+语调气场*0.1+条理性*0.1+逻辑性与说服力最低分*0.5
			verbalExpressScore :=
				languageFluencyScore*0.3 +
					toneScore*0.1 +
					question.MainPointScore*0.1 +
					func() float64 {
						minScore := logicScore
						if minScore > themeScore {
							minScore = themeScore
						}
						return minScore
					}()*0.5
			// 要点评分（在面试过程中，已经给出评分）
			// pointText := question.Question.PointText
			// if len(pointText) != 0 {
			// 	var pointScoreDetail []tables.PointTextDetail
			// 	_ = json.Unmarshal([]byte(pointText), &pts)
			// 	for i := 0; i < len(pts); i++ {
			// 		score := report_service.FetchQScore(ans_text, pts[i].Value)
			// 		pointScoreDetail = append(pointScoreDetail, tables.PointTextDetail{Type: pts[i].Type, Label: pts[i].Label, Value: pts[i].Value, Score: score})
			// 		pointScore += score
			// 	}
			// 	pointScore = 30.0 + 0.7*(pointScore/float64(len(pts)))
			// 	b, _ := json.Marshal(pointScoreDetail)
			// 	updates["main_point_score_detail"] = b
			// }

			// updates["main_point_score"] = pointScore
			updates["asr_score"] = asrScore
			updates["tone"] = toneScore
			updates["mood"] = moodScore
			updates["language_fluency_score"] = languageFluencyScore
			updates["language_score"] = languageScore
			updates["theme_score"] = themeScore
			updates["topic_score"] = topicScore
			updates["character_info"] = string(characterInfoByte)
			updates["performance_score"] = performanceScore
			updates["express_score"] = expressScore
			updates["logic_score"] = logicScore
			updates["verbal_express_score"] = verbalExpressScore
		}
		// 更新对应的评分项
		d := variable.DB.MySQL.Model(&tables.RealQues{}).Where("id = ?", question.ID).Updates(updates).Limit(1)
		if d.Error != nil {
			return d.Error
		}

	}
	return nil
}

// 获取用户自己的报告
func ReportList(ctx *gin.Context) {
	userId := ctx.Param("uid")
	uid, er := strconv.Atoi(userId)
	if er != nil {
		format.NewResponseJson(ctx).Err(500, "非法用户ID")
		return
	}
	reports, err := report_service.FindReportsByUID(uid)
	if err != nil {
		format.NewResponseJson(ctx).SuccessDataList(0)
		return
	}
	format.NewResponseJson(ctx).SuccessDataList(len(reports), reports)
}

// 获取用户的报告
func GetReportList(ctx *gin.Context) {
	var ct model.ReportListReq
	if err := bind.ShouldBinding(ctx, &ct); err != nil {
		format.NewResponseJson(ctx).SuccessDataList(0)
		return
	}
	userId := ctx.Param("uid")
	uid, er := strconv.Atoi(userId)
	if er != nil {
		format.NewResponseJson(ctx).Err(500, "非法用户ID")
		return
	}
	ct.Uid = uid
	reports, err := report_service.FindReportsByWhere(ct)
	if err != nil {
		format.NewResponseJson(ctx).SuccessDataList(0)
		return
	}
	format.NewResponseJson(ctx).SuccessDataList(len(reports), reports)
}

// 表现优异文案获取
func encourageText(score int, s model.Sort) string {
	if score >= 75 {
		if s.CareerId == 0 && s.Criteria == "围绕主题" {
			return fetchSuggestComment(2, score)
		} else if s.CareerId == 0 && s.Criteria == "语言表述" {
			return fetchSuggestComment(1, score)
		} else { // 其他
			cid := strconv.Itoa(int(s.CareerId))
			if cid == "1" { // 说明是岗位能力
				return suggestCommonComments[s.Criteria]["优"]["A"]
			}
			return suggestComments[cid][s.Criteria]["A"]
		}
	}
	return ""
}

func civilAdviserLabel(criteria string, score int) string {
	careerIdStr := "2"
	if score >= 85 {
		return suggestComments[careerIdStr][criteria]["A"]
	} else if score >= 60 {
		return suggestComments[careerIdStr][criteria]["B"]
	} else if score >= 40 {
		return suggestComments[careerIdStr][criteria]["C"]
	} else {
		return suggestComments[careerIdStr][criteria]["D"]
	}
}

// 有待提升文案获取
func promoteText(score int, lackMainPoint int, s model.Sort) string {
	if s.CareerId == tables.QCivilServant {
		return civilAdviserLabel(s.Criteria, score)
	}
	if score <= 75 {
		if s.CareerId == 0 && s.Criteria == "围绕主题" {
			return fetchSuggestComment(2, score)
		} else if s.CareerId == 0 && s.Criteria == "语言表述" {
			return fetchSuggestComment(1, score)
		} else if s.CareerId == 1 && s.Criteria == "逻辑思维能力" { // 通用题库中的逻辑思维能  无需判断要点
			return fetchPromoteComment(strconv.Itoa(int(s.CareerId)), int(s.Score), s.Criteria)
		} else if s.CareerId == 1 { // 需要判断缺少要点
			if lackMainPoint == 1 {
				return suggestCommonComments[s.Criteria]["差"]["A"]
			} else if lackMainPoint == 2 {
				return suggestCommonComments[s.Criteria]["差"]["B"]
			} else if lackMainPoint == 3 {
				return suggestCommonComments[s.Criteria]["差"]["C"]
			} else if lackMainPoint == 4 {
				return suggestCommonComments[s.Criteria]["差"]["D"]
			} else {
				return suggestCommonComments[s.Criteria]["差"]["D"]
			}
		} else {
			return fetchPromoteComment(strconv.Itoa(int(s.CareerId)), int(s.Score), s.Criteria)
		}
	} else if score > 75 && s.CareerId == 1 {
		return suggestCommonComments[s.Criteria]["优"]["A"]
	} else {
		return fetchPromoteComment(strconv.Itoa(int(s.CareerId)), int(s.Score), s.Criteria)
	}
}

func ReportQuery(ctx *gin.Context) {
	// 全局变量只有在程序启动的时候才会查询最新的数据库数据，这里每次生成报告都查数据库，得到最新的话术数据
	skillComments, _ = tables.DefaultTrick.GetSkillTrick()
	abilityComments, _ = tables.DefaultTrick.GetAbilityTrick()
	suggestCommonComments, _ = tables.DefaultTrick.GetCommonSuggestTrick()
	suggestComments, _ = tables.DefaultTrick.GetSuggestTrick()

	var sr services.Sm
	if err := bind.ShouldBinding(ctx, &sr); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "场次ID不合法",
		})
		return
	}
	sessionId := sr.SessionId
	sid, err := strconv.Atoi(sessionId)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "场次ID不合法",
		})
		return
	}

	session, err := services.FindSessionById(sid)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  err.Error(),
		})
		return
	}

	if session.User == nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "当前用户不存在",
		})
		return
	}

	if session.Career == nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "当前职业不存在",
		})
		return
	}

	if session.FinishAt.Unix() <= 0 || session.CreatedAt.Unix() <= 0 || session.Status == 0 {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "当前场次未完成",
		})
		return
	}

	// 评分分支
	if sr.Mark {
		err2 := updateScore(ctx, int(session.ID))
		if err2 != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"code": 500,
				"data": struct{}{},
				"msg":  "打分异常",
			})
			return
		}
	}

	questions, err := services.FindQuestionsBySessionId(int(session.ID))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  err.Error(),
		})
		return
	}
	// 获取平均分 准备数据
	ccf := tables.CommonConf{}
	if d := variable.DB.MySQL.Where("conf_key=? and type=?", tables.ConfKeyAverageScore, tables.AverageScoreType).Find(&ccf); d.Error != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  d.Error.Error(),
		})
		return
	}
	ccfMap := map[string]map[string]float64{}
	if err := json.Unmarshal([]byte(ccf.ConfValue), &ccfMap); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  err.Error(),
		})
		return
	}

	pfa := []interface{}{}
	professionalArr := []model.Ac{}
	st := []model.Sort{}
	characterScore := map[string]float64{}
	// 初始化len
	count := 10
	m := make([]model.ScoreDetail, count) // key:0,1,2,3,4,5,6,7,8,9,10   0:语言流畅度 1:语调气场 2:重点把控力(围绕主题) 3:条理性(要点覆盖) 4:表达能力 5: 表现力 6:自信度(语气词评分) 7：题目测评 8:asr 9:公务员言语表达能力 10:公务员语言逻辑性
	for i := 0; i < count; i++ {          // 初始化
		m[i] = model.ScoreDetail{Sum: 0.00, Avg: 0.00}
	}
	sum := 0

	//补丁: 计算所有题目逻辑思维得分的平均分
	logicTotal := 0.0
	logicQuesCount := 0
	for _, q := range questions {
		if len(q.Question.ParentText) != 0 {
			continue
		}
		logicTotal += q.LogicScore
		logicQuesCount += 1
	}
	logicAvgScore := logicTotal / float64(logicQuesCount)
	hasLogicCriteria := false //判断是否有逻辑思维维度的题目，目前只有产品岗有逻辑思维维度
	//公务员报告总分
	var civilServantTotalScore float64
	for i, question := range questions {
		if len(question.Question.ParentText) != 0 {
			continue
		}
		sum++
		// characterInfo
		characterArr := []model.CharacterInfo{}
		characterInfo := question.CharacterInfo
		if len(characterInfo) != 0 {
			json.Unmarshal([]byte(characterInfo), &characterArr)
			for i := 0; i < len(characterArr); i++ {
				characterScore[characterArr[i].Title] = characterScore[characterArr[i].Title] + characterArr[i].Score
			}
		}

		// 语言流畅度
		m[0].Sum += question.LanguageFluencyScore
		m[0].Scores = append(m[0].Scores, question.LanguageFluencyScore)

		// 语调气场
		m[1].Sum += question.Tone
		m[1].Scores = append(m[1].Scores, question.Tone)

		// 重点把控力(围绕主题)
		m[2].Sum += question.ThemeScore
		m[2].Scores = append(m[2].Scores, question.ThemeScore)

		// 条理性(要点覆盖)
		m[3].Sum += question.MainPointScore
		m[3].Scores = append(m[3].Scores, question.MainPointScore)

		// 表达能力
		// fourScore := (question.LanguageFluencyScore + question.Tone + question.ThemeScore + question.MainPointScore) / 4.0
		m[4].Sum += question.ExpressScore
		m[4].Scores = append(m[4].Scores, question.ExpressScore)

		// 表现力
		// fiveScore := question.LanguageScore*0.5 + question.ThemeScore*0.5
		m[5].Sum += question.PerformanceScore
		m[5].Scores = append(m[5].Scores, question.PerformanceScore)

		// 自信度(语气词评分)
		m[6].Sum += question.Mood
		m[6].Scores = append(m[6].Scores, question.Mood)

		// 题目测评
		m[7].Sum += question.TopicScore
		m[7].Scores = append(m[7].Scores, question.TopicScore)

		// asr
		m[8].Sum += question.AsrScore
		m[8].Scores = append(m[8].Scores, question.AsrScore)

		//公务员言语表达能力
		m[9].Sum += question.VerbalExpressScore
		m[9].Scores = append(m[9].Scores, question.VerbalExpressScore)

		// 专业能力评分
		careerId := strconv.Itoa(int(question.Question.CareerID))
		criteria := question.Question.Criteria
		lowPerformance := abilityComments[careerId][criteria]["缺点"]
		highPerformance := abilityComments[careerId][criteria]["优点"]
		score := int(question.TopicScore)
		civilServantTotalScore += (question.ThemeScore*0.35 + question.MainPointScore*0.65) * civilScoreWeight[criteria]
		if criteria == "逻辑思维能力" {
			hasLogicCriteria = true
			//score = int(logicAvgScore)
		}
		professionalArr = append(professionalArr, model.Ac{
			Label:           criteria,
			Score:           score,
			LowPerformance:  lowPerformance,
			HighPerformance: highPerformance,
		})
		// pdf分页显示，专业能力每3个正好是一页
		if len(professionalArr) == 3 || (session.CareerID == tables.QCivilServant && i == 0) {
			pfa = append(pfa, professionalArr)
			professionalArr = []model.Ac{}
		}
		// 面试指导 建议
		_, num := lackMainPointSum(question.MainPointScoreDetail)
		// label := fetchPromoteComment(careerId, score, criteria)
		cidStr := strconv.Itoa(int(question.Question.CareerID))
		avg := ccfMap[cidStr][criteria]
		entitySt := model.Sort{
			Id:       int(question.ID),
			Score:    score,
			CareerId: question.Question.CareerID,
			Criteria: question.Question.Criteria,
			Title:    criteria,
			Label:    "",
			Average:  avg,
		}
		pText := promoteText(score, num, entitySt)
		entitySt.Label = pText
		st = append(st, entitySt)
	}
	if !hasLogicCriteria && session.CareerID != tables.QCivilServant {
		fmt.Println("[debug] not hasLogicCriteria")
		// pdf分页显示，专业能力每3个正好是一页
		if len(professionalArr) == 3 {
			pfa = append(pfa, professionalArr)
			professionalArr = []model.Ac{}
		}
		fmt.Println("[debug] logicAvgScore: ", logicAvgScore)
		professionalArr = append(professionalArr, model.Ac{
			Label:           "逻辑思维能力",
			Score:           int(logicAvgScore),
			LowPerformance:  abilityComments["4"]["逻辑思维能力"]["缺点"], //这里的4表示产品经理的题库ID
			HighPerformance: abilityComments["4"]["逻辑思维能力"]["优点"],
		})
		st = append(st, model.Sort{
			Id:       0,
			Title:    "逻辑思维能力",
			Label:    fetchPromoteComment("4", int(logicAvgScore), "逻辑思维能力"),
			Score:    int(logicAvgScore),
			Average:  ccfMap["1"]["逻辑思维能力"],
			Criteria: "逻辑思维能力",
			CareerId: 4,
		})
		m[7].Scores = append(m[7].Scores, logicAvgScore)
	}
	if len(professionalArr) > 0 {
		pfa = append(pfa, professionalArr)
	}
	for i := 0; i < count; i++ { // 计算方差 & 平均值
		variance, avg := calculateStandardVariance(m[i].Scores)
		m[i].Variance = variance
		m[i].Avg = avg
	}

	// 公务员情绪控制得分
	var motionControlScore int
	// 人物性格
	var personalityAssessment = []model.Ac{}
	for k, v := range characterScore {
		score := int(v*10) / (sum)
		if k == "神经质" {
			motionControlScore = (10 - score) * 10
		}
		personalityAssessment = append(personalityAssessment, model.Ac{
			Title:           k,
			Score:           score,
			Label:           abilityComments["ocean"][k]["描述"],
			LowPerformance:  abilityComments["ocean"][k]["缺点"],
			HighPerformance: abilityComments["ocean"][k]["优点"],
		})

	}
	// 报告综合得分==题目评测得分  && 将报告得分更新数据库
	var reportScore = int(m[7].Avg)
	//公务员的综合得分的计算规则与其他职业不一致
	if session.CareerID == tables.QCivilServant {
		civilServantTotalScore += m[9].Avg * 0.22
		civilServantTotalScore += float64(motionControlScore) * 0.1
		reportScore = int(civilServantTotalScore)
		//添加言语表达能力面试指导
		st = append(st, model.Sort{
			Id:       0,
			Title:    "言语表达能力",
			Score:    int(m[9].Avg),
			Criteria: "言语表达能力",
			CareerId: 2,
			Label:    civilAdviserLabel("言语表达能力", int(m[0].Avg)),
		})
		st = append(st, model.Sort{
			Id:       0,
			Title:    "自我情绪控制",
			Score:    motionControlScore,
			Criteria: "自我情绪控制",
			CareerId: 2,
			Label:    civilAdviserLabel("自我情绪控制", motionControlScore),
		})
	}
	d := variable.DB.MySQL.Model(&tables.Session{}).Where("id = ?", sessionId).Updates(map[string]interface{}{"total_score": strconv.Itoa(reportScore)}).Limit(1)
	if d.Error != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  err.Error(),
		})
		return
	}

	// 添加语言表述评分
	// st = append(st, entity.Sort{Id: 0, Score: int(m[0].Avg), CareerId: 0, Criteria: "语言表述"}) // 需要特殊处理
	// st = append(st, entity.Sort{Id: 0, Score: int(m[1].Avg), CareerId: 0, Criteria: "围绕主题"}) // 需要特殊处理
	// 面试指导根据Score排序 从大到小排序
	sort.Slice(st, func(i, j int) bool {
		return st[i].Score > st[j].Score
	})
	promotedArr := []model.Sort{}
	advantageArr := []model.Sort{}
	guide := map[string]interface{}{}
	for i := 0; i < len(st); i++ {
		if st[len(st)-i-1].Score <= 60 && len(promotedArr) < 2 {
			promotedArr = append(promotedArr, st[len(st)-i-1])
		}
		if st[i].Score > 75 && len(advantageArr) < 2 {
			advantageArr = append(advantageArr, st[i])
		}
	}
	guide["promotedArr"] = promotedArr
	guide["advantageArr"] = advantageArr

	// reportMsg := []entity.Lv{
	// 	{Label: "姓名", Value: session.User.Name},
	// 	{Label: "训练日期", Value: session.CreatedAt.Format("2006-01-02 03:04:05")},
	// 	{Label: "训练时长", Value: date.SecondsSwitchTime(int(session.FinishAt.Unix() - session.CreatedAt.Unix()))},
	// }
	// 兼容河北招聘网
	var userName = session.User.Name
	var school = session.User.School
	var profession = session.User.Profession
	var grade = session.User.Grade
	if session.User.ID == 1 {
		userName = "-"
		school = "-"
		profession = "-"
		grade = "-"
		// 查询用户名
		interview, _ := new(tables.Interview).GetInterview(int(session.ID))
		if interview.ID != 0 {
			userName = interview.UserName
		}
	}

	userData := []model.Lv{
		{Label: "姓名", Value: userName},
		{Label: "学校", Value: school},
		{Label: "专业", Value: profession},
		{Label: "年级", Value: grade},
		{Label: "训练职业", Value: session.Career.Name},
	}
	interviewDetailData := []model.Da{}

	// 0:语言流畅度 1:语调气场 2:重点把控力(围绕主题) 3:条理性(要点覆盖) 4:表达能力 5: 表现力 6:自信度(语气词评分) 7：题目测评
	interviewState := map[string]interface{}{
		// 表达能力话术
		"presentationSkillsLabel": FetchSkillComment("status_4", m[4].Avg),
		"fluencyData":             m[0].Scores,                                                                          //流畅度图表数据
		"fluencyLabel":            fetchSkillCommentExt("status_0", m[0].Avg, m[0].Variance, m[8].Avg, m[6].Avg, false), //流畅度话术
		"intonationData":          m[1].Scores,                                                                          //语调气场图表数据
		"intonationLabel":         fetchSkillCommentExt("status_1", m[1].Avg, m[1].Variance, 0.0, 0.0, true),            //语调气场话术
		"keyForceLabel":           FetchSkillComment("status_2", m[2].Avg),
		"organizedLabel":          FetchSkillComment("status_3", m[3].Avg),
		"expressiveData":          m[5].Scores, //表现力图表数据
		"expressiveLabel":         fetchSkillCommentExt("status_5", m[5].Avg, m[5].Variance, 0.0, 0.0, true),
		"selfConfidenceData":      m[6].Scores,                                                               //自信度图表数据
		"selfConfidenceLabel":     fetchSkillCommentExt("status_6", m[6].Avg, m[6].Variance, 0.0, 0.0, true), //自信度图表数据
	}
	var photoUrl = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + session.UserPhoto
	duration := session.FinishAt.Sub(session.CreatedAt).Seconds()
	durationStr := fmt.Sprintf("%d分%d秒", int(duration/60), int(duration)%60)
	reportTemplateFile := "report.html"
	if session.CareerID == tables.QCivilServant {
		interviewState["presentationSkillsLabel"] = fetchCivilComment("status_9", m[9].Avg)
		interviewState["logicLabel"] = fetchCivilComment("status_10", logicAvgScore)
		interviewState["emotionsLabel"] = fetchCivilEmotionComment("status_11", float64(motionControlScore))
		reportTemplateFile = "civilServiceReport.html"
		var agent tables.Agent
		variable.DB.MySQL.Where("id=?", session.User.AgentID).First(&agent)
		if agent.School == "北京大学" {
			reportTemplateFile = "beida-civilServiceReport.html"
		}
	}
	ctx.HTML(http.StatusOK, reportTemplateFile, gin.H{
		"time":                  session.FinishAt.Format("2006-01-02 15:04:05"),
		"duration":              durationStr,
		"userImgUrl":            photoUrl,    // 头像url
		"userData":              userData,    // 用户信息
		"interviewScore":        reportScore, // 报告得分
		"professional":          pfa,         // 专业能力
		"interviewDetailArr":    interviewDetailData,
		"guide":                 guide,
		"interviewState":        interviewState,        // 面试表现
		"personalityAssessment": personalityAssessment, // 人格评测
	})
}

// post请求创建报告 更新报告
func ReportCreate(ctx *gin.Context) {
	var sr services.Sr
	if err := bind.ShouldBinding(ctx, &sr); err != nil {
		format.NewResponseJson(ctx).ErrObj(200, err.Error())
		return
	}

	if err := report_service.GenerateReport(ctx, sr.SessionId, true); err != nil {
		format.NewResponseJson(ctx).ErrObj(200, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(struct{}{})
}

// post请求创建报告 更新报告
func ReportCreateNoScore(ctx *gin.Context) {
	var sm services.Sm
	if err := bind.ShouldBinding(ctx, &sm); err != nil {
		format.NewResponseJson(ctx).ErrObj(200, err.Error())
		return
	}
	if sm.Mark {
		if err := report_service.GenerateReport(ctx, sm.SessionId, true); err != nil {
			format.NewResponseJson(ctx).ErrObj(200, err.Error())
			return
		}
	} else {
		if err := report_service.GenerateReport(ctx, sm.SessionId, false); err != nil {
			format.NewResponseJson(ctx).ErrObj(200, err.Error())
			return
		}
	}

	format.NewResponseJson(ctx).SuccessObj(struct{}{})
}

// 新的报告点击配置
func NewReportClick(ctx *gin.Context) {
	userId := ctx.Param("uid")
	uid, er := strconv.Atoi(userId)
	if er != nil {
		format.NewResponseJson(ctx).Err(500, "非法用户ID")
		return
	}
	req := &report_service.NewReportClickReq{}
	req.Uid = uid
	err := ctx.ShouldBindQuery(req)
	if err != nil {
		format.NewResponseJson(ctx).Err(400, "参数错误")
		return
	}

	err = report_service.NewReportClick(req)
	if err != nil {
		format.NewResponseJson(ctx).SuccessDataList(0)
		return
	}
	format.NewResponseJson(ctx).SuccessDataList(0)
}

// GetReport 请求获取报告地址
func GetReport(ctx *gin.Context) {
	var sr services.Sr
	if err := bind.ShouldBinding(ctx, &sr); err != nil {
		format.NewResponseJson(ctx).ErrObj(200, err.Error())
		return
	}

	resp, err := report_service.GetReport(ctx, sr.SessionId)
	if err != nil {
		format.NewResponseJson(ctx).ErrObj(500, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(resp)
}
